# C/C++ GPIO development ***Copyright © Quectel Wireless Solutions Co., Ltd. 2026. All rights reserved.*** --- # lgpio introduction **lgpio** is a GPIO control library for Linux system, providing a simple and easy-to-use C API to operate GPIO, I2C, SPI and other peripherals. ## Main features - **High performance**: C language implementation with high execution efficiency - **Cross-platform compatibility**: Supports various Linux single-board computers - **Rich features**: Supports GPIO, I2C, SPI, PWM and other peripherals - **Easy integration**: Provides standard C API ## Supported features | **Feature** | **Description** | | --- | --- | | GPIO | General purpose input/output | | I2C | I²C bus communication | | SPI | Serial peripheral interface | | PWM | Pulse width modulation | | Notification | GPIO interruptions and event notifications | # Install lgpio ## Install from source code ```bash # Install dependency toolsapt update apt install -y git build-essential # Clone lgpio source codegit clone https://github.com/joan2937/lg.git cd lg # Compile and installmakemake install# Update dynamic linker cache ldconfig ``` ## Verify installation After installation, you can verify with the following commands: ```bash # Check dynamic library ldconfig -p | grep lgpio ``` You should see output similar to `liblgpio.so`. **Other verification methods:** ```bash # Check if library files existls -l /usr/local/lib/liblgpio.* # Check if header file existsls -l /usr/local/include/lgpio.h ``` # GPIO control ## Hardware preparation - Main board - Jumper wires - Multimeter (optional, for measuring voltage) ## GPIO output control The following example demonstrates how to use lgpio to control GPIO pin to output high and low levels. ### Example code Create `gpio_output.c` file: ```c #include #include #include #include int main(int argc, char **argv){if (argc < 3) {printf("Usage: %s \n", argv[0]);printf("Example: %s 36 1 # Set GPIO36 to HIGH\n", argv[0]);return 1;}int gpio_num = atoi(argv[1]);int pin_level = atoi(argv[2]);int h;// Open GPIO chip 4 h = lgGpiochipOpen(4);if (h < 0) {printf("ERROR: %s (%d)\n", lguErrorText(h), h);return 1;}// Set GPIO to output mode and set initial levelint e = lgGpioClaimOutput(h, 0, gpio_num, pin_level);if (e < 0) {printf("ERROR: %s (%d)\n", lguErrorText(e), e);lgGpiochipClose(h);return 1;}printf("GPIO %d set to %s\n", gpio_num, pin_level ? "HIGH (3.3V)" : "LOW (0V)");// Keep the state for 5 secondssleep(5);// Release GPIO resourceslgGpioFree(h, gpio_num);lgGpiochipClose(h);return 0;} ``` ### Compile program ```bash gcc -o gpio_output gpio_output.c -llgpio ``` ### Run test **Test low level:** ```bash sudo ./gpio_output 36 0 ``` Output: `GPIO 36 set to LOW (0V)` **Test high level:** ```bash sudo ./gpio_output 36 1 ``` Output: `GPIO 36 set to HIGH (3.3V)` > **Tip**: GPIO36 corresponds to Pin3 of 40Pin. ## GPIO input reading The following example demonstrates how to read the state of a GPIO pin. ### Example code Create `gpio_input.c` file: ```c #include #include #include #include int main(int argc, char **argv){if (argc < 2) {printf("Usage: %s \n", argv[0]);printf("Example: %s 36 # Read GPIO36 state\n", argv[0]);return 1;}int gpio_num = atoi(argv[1]);int h, e, value;// Open GPIO chip 4 h = lgGpiochipOpen(4);if (h < 0) {printf("ERROR: %s (%d)\n", lguErrorText(h), h);return 1;}// Set GPIO to input mode e = lgGpioClaimInput(h, 0, gpio_num);if (e < 0) {printf("ERROR: %s (%d)\n", lguErrorText(e), e);lgGpiochipClose(h);return 1;}printf("Reading GPIO %d state (press Ctrl+C to exit)...\n", gpio_num);// Loop to read the GPIO statewhile (1) { value = lgGpioRead(h, gpio_num);if (value < 0) {printf("ERROR: %s (%d)\n", lguErrorText(value), value);break;}printf("GPIO %d: %s\n", gpio_num, value ? "HIGH" : "LOW");sleep(1);}// Release resourceslgGpioFree(h, gpio_num);lgGpiochipClose(h);return 0;} ``` ### Compile and run ```bash # Compile gcc -o gpio_input gpio_input.c -llgpio # Runsudo ./gpio_input 36 ``` ## GPIO output feedback test The following example demonstrates how to verify functionality by outputting from one pin and reading from another pin. ### Example code Create `gpio_feedback.c` file: ```c #include #include #include int main(){int h;int gpio_out = 36; // Pin3 - GPIO36int gpio_in = 37; // Pin5 - GPIO37// Open GPIO chip 4 h = lgGpiochipOpen(4);if (h < 0) {printf("ERROR: %s (%d)\n", lguErrorText(h), h);return 1;}// Set GPIO36 as output, GPIO37 as inputint e1 = lgGpioClaimOutput(h, 0, gpio_out, 0);int e2 = lgGpioClaimInput(h, 0, gpio_in);if (e1 < 0 || e2 < 0) {printf("ERROR: Failed to claim GPIO\n");lgGpiochipClose(h);return 1;}printf("=== GPIO Feedback Test ===\n");printf("Output: GPIO%d (Pin3)\n", gpio_out);printf("Input: GPIO%d (Pin5)\n", gpio_in);printf("Please connect Pin3 and Pin5 together\n\n");for (int i = 0; i < 5; i++) {// Set high levellgGpioWrite(h, gpio_out, 1);usleep(100000); // 100msint val_high = lgGpioRead(h, gpio_in);printf("Output: HIGH | Input: %s\n", val_high ? "HIGH" : "LOW");sleep(1);// Set low levellgGpioWrite(h, gpio_out, 0);usleep(100000);int val_low = lgGpioRead(h, gpio_in);printf("Output: LOW | Input: %s\n", val_low ? "HIGH" : "LOW");sleep(1);}// Release resourceslgGpioFree(h, gpio_out);lgGpioFree(h, gpio_in);lgGpiochipClose(h);printf("\nTest completed\n");return 0;} ``` ### Compile and run ```bash # Compile gcc -o gpio_feedback gpio_feedback.c -llgpio # Run (need to short Pin3 and Pin5 first)sudo ./gpio_feedback ``` **Expected output:** ```plaintext === GPIO Feedback Test === Output: GPIO36 (Pin3) Input: GPIO37 (Pin5) Please connect Pin3 and Pin5 together Output: HIGH | Input: HIGH Output: LOW | Input: LOW Output: HIGH | Input: HIGH Output: LOW | Input: LOW ... ``` # GPIO pin mapping Quectel Pi H1 primarily uses `/dev/gpiochip4` for GPIO control. ## Common pin mapping | **Physical pin** | **Pin name** | **GPIO number** | **GPIO chip** | **Default function** | | --- | --- | --- | --- | --- | | Pin3 | NFC_I2C_SDA | 36 | /dev/gpiochip4 | I2C09_SDA | | Pin5 | NFC_I2C_SCL | 37 | /dev/gpiochip4 | I2C09_SCL | | Pin7 | CAM2_RST | 77 | /dev/gpiochip4 | GPIO | | Pin11 | GPIO_16 | 16 | /dev/gpiochip4 | GPIO/SPI/UART/I2C | | Pin13 | GPIO_17 | 17 | /dev/gpiochip4 | GPIO/SPI/UART/I2C | > **Note**: Pin3 and Pin5 are configured as I2C9 interface by default. If you need to use them as GPIO, please ensure no other devices are occupying them. For complete pin mapping, please refer to: [40-Pin expansion](<../../Usage guide/40-Pin expansion/40-Pin expansion.md>) # lgpio API reference ## GPIO chip operations ```c // Open GPIO chipint lgGpiochipOpen(int chip_num);// Close GPIO chipint lgGpiochipClose(int handle); ``` ## GPIO configuration ```c // Claim GPIO as output modeint lgGpioClaimOutput(int handle, int flags, int gpio, int level);// Claim GPIO as input modeint lgGpioClaimInput(int handle, int flags, int gpio);// Release GPIOint lgGpioFree(int handle, int gpio); ``` ## GPIO read/write ```c // Read GPIO levelint lgGpioRead(int handle, int gpio);// Write GPIO levelint lgGpioWrite(int handle, int gpio, int level); ``` ## PWM control ```c // Output PWM signalint lgTxPwm(int handle, int gpio, float freq, float duty, int offset, int cycles); ``` # Common issues ## Compilation errors **Issue: Cannot find lgpio.h** ```plaintext fatal error: lgpio.h: No such file or directory ``` **Solution:** 1. Confirm that lgpio library is installed 2. Check header file path: `ls /usr/local/include/lgpio.h` 3. If the header file is in other path, specify the path during compilation: `gcc -I/path/to/include ...` ## Runtime errors **Issue: Permission denied** **Solution:** Run the program with `sudo`: ```bash sudo ./gpio_output 36 1 ``` **Issue: Cannot find shared library** ```plaintext error while loading shared libraries: liblgpio.so ``` **Solution:** ```bash # Update dynamic linker cachesudo ldconfig # Or set LD_LIBRARY_PATHexport LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH ``` ## Pin occupancy issue If you encounter an error indicating that the GPIO is already occupied, use the following command to check: ```bash # View GPIO state gpioinfo | grep -A 180 "gpiochip4" | grep -E "(line 36|line 37|consumer)" ``` If the pin is occupied, you need to release it first or select another unoccupied pin. # Reference resources - [lgpio GitHub repository]() - [lgpio official documentation]() - [40-Pin expansion](<../../Usage guide/40-Pin expansion/40-Pin expansion.md>) - [Python GPIO development](<../Python GPIO development/Python GPIO development.md>)